#include "Task.h"

#include "MetaUnitVariable.h"
#include "BuildUnit.h"

#include "..\Util.h"

namespace BroodWar
{
	namespace Addon
	{
		Task^ ConvertTask(BWSAL::Task* task)
		{
			if(task == NULL)
				return nullptr;
			return gcnew Task(task);
		}

		BWSAL::Task* ConvertTask(Task^ task)
		{
			if(task == nullptr)
				return NULL;
			return task->instance;
		}

		Task::Task(BWSAL::Task* task)
		{
			instance = task;
			dispose = false;
		}
		
		Task::Task(BWSAL::Task task)
		{
			instance = new BWSAL::Task(task);
			dispose = true;
		}
		
		Task::~Task()
		{
			if(dispose)
				delete instance;
		}
		
		Task::!Task()
		{
			if(dispose)
				delete instance;
		}
		
		Task::Task()
		{
			instance = new BWSAL::Task();
			dispose = true;
		}
		
		Task::Task(Addon::BuildType type)
		{
			instance = new BWSAL::Task(ConvertBuild(type));
			dispose = true;
		}

		int Task::Id::get()
		{
			return instance->getID();
		}
			
		Build^ Task::BuildType::get()
		{
			return ConvertBuild(instance->getBuildType());
		}
		
		MetaUnitVariable^ Task::Builder::get()
		{
			return ConvertMetaUnitVariable(instance->getBuilder());
		}
		
		MetaUnitVariable^ Task::SecondBuilder::get()
		{
			return ConvertMetaUnitVariable(instance->getSecondBuilder());
		}
		
		BuildUnit^ Task::CreatedUnit::get()
		{
			return ConvertBuildUnit(instance->getCreatedUnit());
		}
		
		BuildUnit^ Task::SecondCreatedUnit::get()
		{
			return ConvertBuildUnit(instance->getSecondCreatedUnit());
		}
		
		TilePosition^ Task::BuildLocation::get()
		{
			return ConvertTile(instance->getBuildLocation());
		}
		
		TilePosition^ Task::SeedLocation::get()
		{
			return ConvertTile(instance->getSeedLocation());
		}
		
		BuildEvent^ Task::GetReserveBuilderEvent()
		{
			return ConvertBuildEvent(instance->getReserveBuilderEvent());
		}
		
		BuildEvent^ Task::GetReserveResourcesEvent()
		{
			return ConvertBuildEvent(instance->getReserveResourcesEvent());
		}
		
		BuildEvent^ Task::GetReleaseBuilderEvent()
		{
			return ConvertBuildEvent(instance->getReleaseBuilderEvent());
		}
		
		BuildEvent^ Task::GetCompleteBuildTypeEvent()
		{
			return ConvertBuildEvent(instance->getCompleteBuildTypeEvent());
		}
		
		bool Task::IsScheduledThisFrame::get()
		{
			return instance->isScheduledThisFrame();
		}
		
		bool Task::IsWaiting::get()
		{
			return instance->isWaiting();
		}
		
		bool Task::IsRunning::get()
		{
			return instance->isRunning();
		}
		
		bool Task::IsCompleted::get()
		{
			return instance->isCompleted();
		}
		
		TaskState^ Task::State::get()
		{
			return ConvertTaskState(instance->getState());
		}

		void Task::State::set(TaskState^ value)
		{
			instance->setState(ConvertTaskState(value));
		}
		
		int Task::EarliestStartTime::get()
		{
			return instance->getEarliestStartTime();
		}
		
		void Task::EarliestStartTime::set(int value)
		{
			instance->setEarliestStartTime(value);
		}
		
		int Task::RunTime::get()
		{
			return instance->getRunTime();
		}
		
		void Task::RunTime::set(int value)
		{
			instance->setRunTime(value);
		}
		
		int Task::ExecuteTime::get()
		{
			return instance->getExecuteTime();
		}
		
		void Task::ExecuteTime::set(int value)
		{
			instance->setExecuteTime(value);
		}
		
		int Task::CompletionTime::get()
		{
			return instance->getCompletionTime();
		}
		
		void Task::CompletionTime::set(int value)
		{
			instance->setCompletionTime(value);
		}
		
		int Task::LastOrderTime::get()
		{
			return instance->getLastOrderTime();
		}
		
		void Task::SetLastOrderTime()
		{
			instance->setLastOrderTime();
		}
		
		bool Task::IsRelocatable::get()
		{
			return instance->isRelocatable();
		}
		
		void Task::IsRelocatable::set(bool value)
		{
			instance->setRelocatable(value);
		}
		
		void Task::SetScheduledThisFrame()
		{
			instance->setScheduledThisFrame();
		}
		
		void Task::SetBuildLocation(TilePosition^ location)
		{
			instance->setBuildLocation(ConvertTile(location));
		}
		
		void Task::SetSeedLocation(TilePosition^ location)
		{
			instance->setSeedLocation(ConvertTile(location));
		}
		
		void Task::AssignBuilder(IMetaUnit^ builder)
		{
			instance->assignBuilder(ConvertMetaUnit(builder));
		}
		
		void Task::AssignBuilders(IMetaUnit^ builder, IMetaUnit^ secondBuilder)
		{
			instance->assignBuilders(ConvertMetaUnit(builder), ConvertMetaUnit(secondBuilder));
		}
		
		void Task::AssignBuilders(IEnumerable<IMetaUnit^>^ builders)
		{
			instance->assignBuilders(ToSet<IMetaUnit^, BWSAL::MetaUnit*>(builders, &ConvertMetaUnit));
		}
		
		void Task::UseAnyBuilder()
		{
			instance->useAnyBuilder();
		}
		
		bool Task::CanUseAnyBuilder::get()
		{
			return instance->canUseAnyBuilder();
		}
			
		String^ Task::ToString()
		{
			return gcnew String(instance->toString().c_str());
		}
	}
}

/*
#pragma once
#include <BWSAL/BuildType.h>
#include <BWSAL/TaskState.h>
#include <BWAPI.h>
#include <BWSAL/BuildEvent.h>
namespace BWSAL
{
  class BuildUnit;
  class MetaUnit;
  class MetaUnitVariable;
  class TaskStream;
  class BuildingPlacer;
  class Task
  {
    friend class TaskScheduler;
    friend class TaskExecutor;
    public:
      Task( BuildType type = BuildTypes::None );
      int getID() const;
      std::string toString() const;
      BuildType getBuildType() const;
      MetaUnitVariable* getBuilder() const;
      MetaUnitVariable* getSecondBuilder() const;
      BuildUnit* getCreatedUnit() const;
      BuildUnit* getSecondCreatedUnit() const;
      BWAPI::TilePosition getBuildLocation() const;
      BWAPI::TilePosition getSeedLocation() const;
      BuildEvent getReserveBuilderEvent() const;
      BuildEvent getReserveResourcesEvent() const;
      BuildEvent getReleaseBuilderEvent() const;
      BuildEvent getCompleteBuildTypeEvent() const;
      // returns true if this task has been scheduled on this frame
      bool isScheduledThisFrame() const;
      // returns true if the start time has occurred, but the completion time has not
      bool isWaiting() const;
      bool isRunning() const;
      bool isCompleted() const;
      TaskState getState() const;
      void setState( TaskState state );
      int getEarliestStartTime() const;
      void setEarliestStartTime( int time );
      int getRunTime() const;
      void setRunTime( int time );
      int getExecuteTime() const;
      void setExecuteTime( int time );
      int getCompletionTime() const;
      void setCompletionTime( int time );
      int getLastOrderTime() const;
      void setLastOrderTime();
      bool isRelocatable() const;
      void setRelocatable( bool relocatable );
      // sets scheduled to true for the current frame
      void setScheduledThisFrame();
      void setBuildLocation( BWAPI::TilePosition buildLocation );
      void setSeedLocation( BWAPI::TilePosition seedLocation );
      void assignBuilder( MetaUnit* builder );
      void assignBuilders( MetaUnit* builder, MetaUnit* secondBuilder );
      void assignBuilders( std::set< MetaUnit* > builders );
      void useAnyBuilder();
      bool canUseAnyBuilder() const;

    protected:
      BuildType m_type;
      int m_lastScheduledTime;
      int m_earliestStartTime;
      int m_runTime;
      int m_executeTime;
      int m_completionTime;
      int m_lastOrderTime;
      bool m_relocatable;
      int id;
      TaskState m_state;
      MetaUnitVariable* m_builder;
      MetaUnitVariable* m_secondBuilder;
      BuildUnit* m_createdUnit;
      BuildUnit* m_secondCreatedUnit;
      std::set< MetaUnit* > m_possibleBuilders;
      bool m_useAnyBuilder;
      BWAPI::TilePosition m_buildLocation;
      BWAPI::TilePosition m_seedLocation;
      BuildingPlacer* m_buildingPlacer;
      static int s_nextFreeTaskID;
  };
}
*/